import { useUIStore } from "@/store/uiStore";
import { useItemStore } from "@/store/itemStore";
import { getScreenSize, loadImage } from "@/utils";
import Inventory from "@/assets/images/inventory.png";
import { ItemQuality, ItemType, type IItemInstance } from "@/type/item";

/**
 * 背包UI
 */
export class InventoryUI {
  private uiStore = useUIStore();
  private slots: {
    // 背包格子
    x: number;
    y: number;
    width: number;
    height: number;
    type: "hotbar" | "inventory";
    slotId: number; // 槽位ID
  }[] = [];
  private slotSize = 42; // 格子大小
  private slotSpacing = 6; // 格子间距
  private itemStore = useItemStore();
  private itemImages: Record<string, HTMLImageElement> = {}; // 物品图片缓存

  // 拖动相关状态
  private isDragging = false; // 是否正在拖动
  private draggedSlotId: number | null = null; // 被拖动的槽位ID
  private draggedItemX = 0; // 拖动中的物品X坐标
  private draggedItemY = 0; // 拖动中的物品Y坐标
  private tooltipX = 0; // 提示框的X坐标
  private tooltipY = 0; // 提示框的Y坐标
  private tooltipPadding = 10; // 提示框的内边距
  private tooltipBorderWidth = 4; // 提示框的宽边宽度
  private tooltipMaxWidth = 300; // 提示框的最大宽度

  // 提示框相关属性
  private showTooltip = false; // 是否显示提示框
  private tooltipItem: IItemInstance | null = null; // 提示框显示的物品
  private hoveredSlotId: number | null = null;

  constructor() {
    const { width: screenWidth, height: screenHeight } = getScreenSize();

    this.itemStore.initInventory(12, 36);

    loadImage(Inventory).then((image) => {
      this.uiStore.registerElement("inventoryBg", {
        visible: false,
        zIndex: 20,
        resources: image,
        type: "inventory",
        sourceRect: {
          x: 0,
          y: 0,
          width: 640, // 根据实际图片尺寸调整
          height: 435, // 根据实际图片尺寸调整
        },
        position: {
          x: screenWidth / 2 - 320, // 居中显示
          y: screenHeight / 2 - 150,
        },
        size: {
          width: 640,
          height: 435,
        },
      });
      this.initializeSlots();
      this.preloadItemImages();
    });
  }

  /**
   * 预加载物品图片
   */
  private async preloadItemImages() {
    // 获取所有物品的图片URL
    const imageUrls = new Set<string>();

    this.itemStore.inventory.forEach((slot) => {
      if (slot.item) {
        imageUrls.add(slot.item.item.imageUrl);
      }
    });

    // 加载所有图片
    for (const url of imageUrls) {
      try {
        this.itemImages[url] = await loadImage(url);
      } catch (error) {
        console.error(`加载物品图片失败: ${url}`, error);
      }
    }
  }

  /**
   * 初始化背包格子
   */
  private initializeSlots() {
    const element = this.uiStore.uiElements["inventoryBg"];
    if (!element || !element.position) return;

    const startX = element.position.x + 33;
    const startY = element.position.y + 31;
    const rowGap = 60;

    this.slots = [];

    for (let i = 0; i < 12; i++) {
      this.slots.push({
        x: startX + i * (this.slotSize + this.slotSpacing),
        y: startY,
        width: this.slotSize,
        height: this.slotSize,
        type: "hotbar",
        slotId: i,
      });
    }

    for (let i = 0; i < 12; i++) {
      this.slots.push({
        x: startX + i * (this.slotSize + this.slotSpacing),
        y: startY + rowGap,
        width: this.slotSize,
        height: this.slotSize,
        type: "inventory",
        slotId: 12 + i,
      });
    }

    for (let i = 0; i < 12; i++) {
      this.slots.push({
        x: startX + i * (this.slotSize + this.slotSpacing),
        y: startY + rowGap + this.slotSize + this.slotSpacing + 2,
        width: this.slotSize,
        height: this.slotSize,
        type: "inventory",
        slotId: 24 + i,
      });
    }
  }

  /**
   * 显示或隐藏背包
   */
  toggle() {
    const element = this.uiStore.uiElements["inventoryBg"];
    if (element) {
      element.visible = !element.visible;
    }
  }

  /**
   * 处理鼠标点击事件
   * @param x 鼠标X坐标
   * @param y 鼠标Y坐标
   */
  handleClick(x: number, y: number) {
    const element = this.uiStore.uiElements["inventoryBg"];
    if (!element || !element.visible) return;

    // 如果正在拖动，则处理拖放
    if (this.isDragging && this.draggedSlotId !== null) {
      // 查找目标槽位
      for (const slot of this.slots) {
        if (
          x >= slot.x &&
          x <= slot.x + slot.width &&
          y >= slot.y &&
          y <= slot.y + slot.height
        ) {
          // 如果拖放到不同的槽位，则交换物品
          if (slot.slotId !== this.draggedSlotId) {
            this.swapItems(this.draggedSlotId, slot.slotId);
          }

          // 结束拖动
          this.isDragging = false;
          this.draggedSlotId = null;
          return;
        }
      }

      // 如果没有拖放到任何槽位，则取消拖动
      this.isDragging = false;
      this.draggedSlotId = null;
      return;
    }

    // 如果不是拖动，则选中槽位
    for (const slot of this.slots) {
      if (
        x >= slot.x &&
        x <= slot.x + slot.width &&
        y >= slot.y &&
        y <= slot.y + slot.height
      ) {
        // 选中槽位
        this.itemStore.selectedSlot = slot.slotId;
        return;
      }
    }
  }

  /**
   * 处理鼠标按下事件
   * @param x 鼠标X坐标
   * @param y 鼠标Y坐标
   */
  handleMouseDown(x: number, y: number) {
    const element = this.uiStore.uiElements["inventoryBg"];
    if (!element || !element.visible) return;

    // 查找点击的槽位
    for (const slot of this.slots) {
      if (
        x >= slot.x &&
        x <= slot.x + slot.width &&
        y >= slot.y &&
        y <= slot.y + slot.height
      ) {
        // 检查槽位是否有物品
        const inventorySlot = this.itemStore.inventory.find(
          (s) => s.id === slot.slotId
        );
        if (inventorySlot && inventorySlot.item) {
          // 开始拖动
          this.isDragging = true;
          this.draggedSlotId = slot.slotId;
          this.draggedItemX = x;
          this.draggedItemY = y;
        }
        return;
      }
    }
  }

  /**
   * 处理鼠标移动事件
   * @param x 鼠标X坐标
   * @param y 鼠标Y坐标
   */
  handleMouseMove(x: number, y: number) {
    const element = this.uiStore.uiElements["inventoryBg"];
    if (!element || !element.visible) return;

    if (this.isDragging) {
      this.draggedItemX = x;
      this.draggedItemY = y;

      if (this.showTooltip && this.tooltipItem) {
        this.tooltipX = x;
        this.tooltipY = y;
      }
      return;
    }

    // 重置悬停状态和提示框状态
    this.hoveredSlotId = null;
    this.showTooltip = false;
    this.tooltipItem = null;

    // 检查鼠标是否悬停在某个槽位上
    for (const slot of this.slots) {
      if (
        x >= slot.x &&
        x <= slot.x + slot.width &&
        y >= slot.y &&
        y <= slot.y + slot.height
      ) {
        // 检查槽位是否有物品
        const inventorySlot = this.itemStore.inventory.find(
          (s) => s.id === slot.slotId
        );

        if (inventorySlot && inventorySlot.item) {
          this.hoveredSlotId = slot.slotId;

          this.showTooltip = true;
          this.tooltipItem = inventorySlot.item;
          this.tooltipX = x;
          this.tooltipY = y;
        }
        break;
      }
    }
  }

  /**
   * 交换两个槽位的物品
   * @param fromSlotId 源槽位ID
   * @param toSlotId 目标槽位ID
   */
  swapItems(fromSlotId: number, toSlotId: number) {
    const fromSlot = this.itemStore.inventory.find((s) => s.id === fromSlotId); // 从哪个槽位交换
    const toSlot = this.itemStore.inventory.find((s) => s.id === toSlotId); // 到哪个槽位交换

    if (!fromSlot || !toSlot) return;

    // 交换物品
    const tempItem = fromSlot.item;
    fromSlot.item = toSlot.item;
    toSlot.item = tempItem;
  }

  /**
   * 渲染背包UI
   * @param ctx 画布上下文
   * @param uiCanvasRef 画布DOM元素
   */
  render(ctx: CanvasRenderingContext2D, uiCanvasRef: HTMLCanvasElement) {
    if (!ctx || !uiCanvasRef) return;

    const uiElements = this.uiStore.uiElements;
    const element = uiElements["inventoryBg"];

    if (!element || !element.visible) return;

    if (
      element.resources &&
      element.sourceRect &&
      element.position &&
      element.size
    ) {
      const destX = Math.floor(element.position.x);
      const destY = Math.floor(element.position.y);
      const destWidth = Math.floor(element.size.width);
      const destHeight = Math.floor(element.size.height);

      ctx.drawImage(
        element.resources,
        element.sourceRect.x,
        element.sourceRect.y,
        element.sourceRect.width,
        element.sourceRect.height,
        destX,
        destY,
        destWidth,
        destHeight
      );
    }

    // this.renderSlots(ctx);
    this.renderItems(ctx);

    if (this.showTooltip && this.tooltipItem) {
      this.renderToolTip(ctx);
    }
  }

  /**
   * 渲染物品提示框
   * @param ctx 画布上下文
   */
  private renderToolTip(ctx: CanvasRenderingContext2D) {
    if (!ctx || !this.tooltipItem) return;

    const item = this.tooltipItem.item;

    // 计算提示框的内容
    const lines: string[] = [];
    lines.push(item.name);

    if (item.type === ItemType.TOOL) {
      lines.push("工具");
    }

    if (item.description) {
      lines.push(item.description);
    }

    ctx.font = "16px Arial";
    let maxLineWidth = 0;
    for (const line of lines) {
      const lineWidth = ctx.measureText(line).width; // 计算文本宽度
      maxLineWidth = Math.max(maxLineWidth, lineWidth);
    }

    // 计算提示框的大小
    const tooltipWidth = Math.min(
      this.tooltipMaxWidth,
      maxLineWidth + this.tooltipPadding * 2
    );
    // 所有文本总高度 + 上下内边距
    const tooltipHeight = lines.length * 24 + this.tooltipPadding * 2;

    // 调整提示框位置，确保不超出屏幕
    let tooltipX = this.tooltipX + 20; // 鼠标右侧20像素
    let tooltipY = this.tooltipY - 10;

    if (tooltipX + tooltipWidth > window.innerWidth) {
      tooltipX = this.tooltipX - tooltipWidth - 20; // 放到鼠标左侧
    }

    if (tooltipY + tooltipHeight > window.innerHeight) {
      tooltipY = window.innerHeight - tooltipHeight - 10; // 放到鼠标右侧
    }

    const borderWidth = 4;
    const cornerRadius = 8;

    ctx.fillStyle = "rgba(70, 45, 10, 0.95)"; // 深棕色背景

    // 绘制提示框边框
    ctx.strokeStyle = "#a67c52"; // 棕色边框
    ctx.lineWidth = this.tooltipBorderWidth;

    // 使用路径绘制圆角边框
    this.drawRoundedRect(
      ctx,
      tooltipX,
      tooltipY,
      tooltipWidth,
      tooltipHeight,
      cornerRadius
    );
    ctx.stroke();

    // 绘制提示框内容
    ctx.fillStyle = "#ffffff"; // 白色文字
    ctx.textBaseline = "top";

    // 绘制标题（物品名称）
    ctx.font = "bold 18px Arial";
    ctx.fillStyle = this.getQualityColor(
      this.tooltipItem.quality || ItemQuality.NORMAL
    );
    ctx.fillText(
      lines[0],
      tooltipX + this.tooltipPadding,
      tooltipY + this.tooltipPadding
    );

    // 绘制其他内容
    ctx.font = "16px Arial";
    ctx.fillStyle = "#ffffff";
    for (let i = 1; i < lines.length; i++) {
      ctx.fillText(
        lines[i],
        tooltipX + this.tooltipPadding,
        tooltipY + this.tooltipPadding + i * 24
      );
    }

    console.log("tooltipX", tooltipX);
  }

  /**
   * 获取品质颜色
   * @param quality 物品品质
   * @returns 品质颜色
   */
  private getQualityColor(quality: ItemQuality): string {
    switch (quality) {
      case ItemQuality.NORMAL:
        return "#ffffff"; // 白色
      case ItemQuality.SILVER:
        return "#c0c0c0"; // 银色
      case ItemQuality.GOLD:
        return "#ffd700"; // 金色
      case ItemQuality.IRIDIUM:
        return "#e066ff"; // 紫色
      default:
        return "#ffffff";
    }
  }

  /**
   * 渲染背包格子描边
   * @param ctx 画布上下文
   */
  private renderSlots(ctx: CanvasRenderingContext2D) {
    if (!ctx) return;

    ctx.strokeStyle = "#a67c52";
    ctx.lineWidth = 2;

    for (const slot of this.slots) {
      ctx.strokeRect(slot.x, slot.y, slot.width, slot.height);

      if (slot.slotId === this.itemStore.selectedSlot) {
        ctx.fillStyle = "rgba(255, 255, 255, 0.3)";
        ctx.fillRect(slot.x, slot.y, slot.width, slot.height);
      }
    }
  }

  /**
   * 渲染物品
   */
  private renderItems(ctx: CanvasRenderingContext2D) {
    if (!ctx) return;

    // 遍历所有槽位
    for (const slot of this.slots) {
      // 如果当前槽位正在被拖动则跳过
      if (this.isDragging && this.draggedSlotId === slot.slotId) continue;

      const inventorySlot = this.itemStore.inventory.find(
        (s) => s.id === slot.slotId
      );

      if (!inventorySlot || !inventorySlot.item) continue;

      const item = inventorySlot.item;
      const itemData = item.item;
      const image = this.itemImages[itemData.imageUrl];

      if (!image) continue;

      // 绘制物品图标
      const drawWidth = itemData.sourceRect.drawWidth;
      const drawHeight = itemData.sourceRect.drawHeight;
      const iconX =
        slot.x + (slot.width - drawWidth) / 2 + itemData.sourceRect.offsetX;
      const iconY =
        slot.y + (slot.height - drawHeight) / 2 + itemData.sourceRect.offsetY;

      ctx.drawImage(
        image, // 图片资源
        itemData.sourceRect.x, // 图片裁剪区域X坐标
        itemData.sourceRect.y, // 图片裁剪区域Y坐标
        itemData.sourceRect.width, // 图片裁剪区域宽度
        itemData.sourceRect.height, // 图片裁剪区域高度
        iconX, // 绘制位置X坐标
        iconY, // 绘制位置Y坐标
        drawWidth, // 绘制宽度
        drawHeight // 绘制高度
      );
    }

    // 绘制正在被拖动的物品
    if (this.isDragging && this.draggedSlotId !== null) {
      const inventorySlot = this.itemStore.inventory.find(
        (s) => s.id === this.draggedSlotId
      );

      if (inventorySlot && inventorySlot.item) {
        const item = inventorySlot.item;
        const itemData = item.item;
        const image = this.itemImages[itemData.imageUrl];

        if (image) {
          const drawWidth = itemData.sourceRect.drawWidth;
          const drawHeight = itemData.sourceRect.drawHeight;
          const iconX = this.draggedItemX - drawWidth / 2;
          const iconY = this.draggedItemY - drawHeight / 2;

          // 半透明效果
          ctx.globalAlpha = 0.7;
          ctx.drawImage(
            image,
            itemData.sourceRect.x,
            itemData.sourceRect.y,
            itemData.sourceRect.width,
            itemData.sourceRect.height,
            iconX,
            iconY,
            drawWidth,
            drawHeight
          );
          ctx.globalAlpha = 1.0; // 恢复透明度
        }
      }
    }
  }

  /**
   * 绘制圆角矩形
   */
  private drawRoundedRect(
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    width: number,
    height: number,
    radius: number
  ) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
    ctx.fill();
  }
}
